<?php
/**
 * Created by PhpStorm.
 * User: LiuJiaJun
 * Date: 2019/1/7
 * Time: 13:32
 */

namespace api\storage\service\output;


use api\storage\common\FileDataTemplate;
use api\storage\model\BomModel;
use api\storage\model\SupplierMaterielModel;
use api\storage\service\MaterielService;
use think\Debug;

class ForeignOutputService extends BaseOutputService
{

    public function getLackMateriel($bomUuid, $supplierId)
    {
        $where['bom_uuid'] = $bomUuid;
        $where['supplier_id'] = $supplierId;
        $where['b.count'] = array('lt', 0);
        //这里已将iwh_supplier_materiel的count负数（欠料）转为正
        $result = $this->bomDetailModel->queryBomDetailLackMaterial($where)->toArray();
        $cache = [];
        foreach ($result as $item) {
            $cache[$item['sub_materiel_id']] = FileDataTemplate::outputRecordData($item['count'], $item['count'], 0, -$item['count']);
        }
        return $this->returnPreviousProcessMaterielTemplate($result, $cache);
    }

    public function getBomMateriel($bomUuid, $supplierId)
    {
        Debug::remark('getBomMaterielStart');
        $this->logger->debug("计算委外出库数量==========开始============");
        $where['bom_uuid'] = $bomUuid;
        $where['supplier_id'] = $supplierId;
        $where1['bom_uuid'] = $bomUuid;
        //厂商表里的库存数量
        $ownMateriel = $this->bomDetailModel->querySupplierMaterielWithBom($where)->toArray();
        $materielArr = $this->makeKeyValueArray($ownMateriel, 'sub_materiel_id');
        $record = [];//将计划出库的料记录下来
        $special = []; //将出库数量为0的记录下来
        $result = $this->bomDetailModel->queryBomByUuid($bomUuid)->toArray();

        $bomDetailCount = count($result);
        for ($i = 0; $i < $bomDetailCount; $i++) {
            $materielId = $result[$i]['sub_materiel_id'];
            $originCount = $result[$i]['count'];

            $materielItem = isset($materielArr[$materielId]) ? $materielArr[$materielId] : null;
            //没有厂商物料库存信息
            if ($this->isEmpty($materielItem)) {
                $record = $this->appendRecordArray($record, $materielId, $originCount, $originCount);
                continue;
            }
            //出库数量为0
            if ($originCount == 0) {
                $special = $this->appendSpecialArray($special, $materielId, 0, 0);
                unset($result[$i]);
                continue;
            }
            $planCount = $originCount - $materielItem['count'];
            $storeCount = $materielItem['count'];
            $type = $materielItem['type'];
            $minCount = $materielItem['min_quantity'];

            if ($planCount > 0) {
                $record = $this->appendRecordArray($record, $materielId, $originCount, $planCount, $storeCount);
                $result[$i]['count'] = $planCount;
            } elseif ($planCount < 0 && $type == 'A') {
                //如果是A类物料并且该物料的库存小于最小包装数的话，
                //并且仓库的物料比这需要出库的物料（一盘，最小包装数量）更多
                //并且这个厂商是SMT，那么需要将该物料出库
                $sum = MaterielService::getSumCount($materielId, $this->storageUuid);
                if ($storeCount < $minCount && $minCount <= $sum && $this->smtSupplier == $supplierId) {
                    //应发改成最小包装数量
                    $record = $this->appendRecordArray($record, $materielId, $originCount, $minCount, 0, 0, true);
                    $strLog = "最小包装出库===>物料：%s，出库数量：%d，库存数量：%d，最小包装数量：%d";
                    $this->logger->info(sprintf($strLog, $materielId, $originCount, $storeCount, $minCount));
                } else {
                    //实际出库数量小于0，的记录下来
                    $special = $this->appendSpecialArray($special, $materielId, $originCount, 0);
                    //将这个物料从投料清单去除
                    unset($result[$i]);
                }
            } else {
                $this->logger->info("记录厂商库存大于等于投料单数量的物料：{$materielId}，库存数量为：{$storeCount}，投料数量为：{$originCount}");
                //实际出库数量小于0，的记录下来
                $special = $this->appendSpecialArray($special, $materielId, $originCount, 0);
                //将这个订单从投料清单去除
                unset($result[$i]);
            }

        }
        Debug::remark("getBomMaterielEnd");
        $time = Debug::getRangeTime('getBomMaterielStart', 'getBomMaterielEnd', 6) . 's';
        $this->logger->debug("计算委外出库数量==========结束（耗时：{$time}）============");
        return $this->returnPreviousProcessMaterielTemplate($result, $record, $special);
    }

    private function appendRecordArray($record, $key, $originalCount, $planCount, $storeCount = 0, $currentCount = 0, $isMinQuantity = false)
    {
        $record[$key] = FileDataTemplate::outputRecordData($originalCount, $planCount, $currentCount, $storeCount, $isMinQuantity);
        return $record;
    }

    private function appendSpecialArray($special, $key, $originalCount = 0, $actualCount = 0)
    {
        $special[$key] = [
            'originalCount' => $originalCount,//投料数量，
            'actualCount' => $actualCount //实发数量，就是最终出库的数量
        ];
        return $special;
    }


    public function handleComplete($bomId, $data, $supplierId, $bomUuid)
    {
        Debug::remark("handleCompleteForeignStart");
        $this->logger->debug("委外单结算：=========开始==========");
        $flag = true;
        $logStr = "计算库存===>出库单：" . $bomId . "厂商：" . $supplierId . "，物料号：%s,原始库存：%d，现在库存：%d，扣除/增加库存：%d";
        $smModel = new SupplierMaterielModel();
        foreach ($data['recordData'] as $materielId => $item) {
            $count = $item['currentCount'] - $item['planCount'];
            $storeCount = $item['storeCount'];
            $isMinQuantity = isset($item['isMinQuantity']) && $item['isMinQuantity'] === true;
            if ($count == 0 && !$isMinQuantity && $storeCount == 0) {
                //这里还是应该是count，calculateCount是一个修正的数据，currentCount才是真正表示出库多少的数据
                continue;
            }
            if ($flag) {
                $flag = $count < 0 ? false : true;
            }
            //判断是不是最小包装的物料，如果是的话，那就将出库的数量（currentCount和calculateCount都行）
            //减去投料单的数量，这样做的原因是把，最小包装出的（多出）的库存加起来
            //这里不要考虑$count分支的问题，如果没有厂商库存记录的话，也就没有最小包装出库一说
            if ($isMinQuantity) {
                $minTmp = "物料号:：%s，是最小包装的物料，投料数量：%d，应发(最小包装)数量：%d，实发数量：%d";
                $this->logger->info(sprintf($minTmp, $materielId, $item['originalCount'], $item['planCount'], $item['currentCount']));
                //实际上的库存应该加上 (currentCount 减去投料的数量)
                //假设  投料 800  存库900  最小包装1000。那么出库完后的库存应该是1100 = 900 + (1000 - 800 )
//                $storeCount = $item['originalCount'] - $item['currentCount'];
                $count = $item['currentCount'] - $item['originalCount'];
            }
            $supplierMateriel = $smModel->findByIdAndMaterielId($supplierId, $materielId);
            if (empty($supplierMateriel) || empty($supplierMateriel->getData())) {
                $addData['supplier_id'] = $supplierId;
                $addData['sub_materiel_id'] = $materielId;
                $addData['count'] = $count;
                $smModel->add($addData);
                $this->logger->debug(sprintf($logStr, $materielId, 0, $count, $count));
            } else {
                $oldDbCount = $supplierMateriel->getData('count');
                $newDbCount = $oldDbCount + $count + (-$storeCount);
                $smModel->updateCount($supplierMateriel->getData('uuid'), ['count' => $newDbCount]);
                $this->logger->debug(sprintf($logStr, $materielId, $oldDbCount, $newDbCount, $newDbCount - $oldDbCount));
            }
        }

        $this->handleSpecialMateriel($bomId, $data['specialData'], $supplierId);
        Debug::remark("handleCompleteForeignEnd");
        $time = Debug::getRangeTime('handleCompleteForeignStart', 'handleCompleteForeignEnd', 6) . 's';
        $this->logger->debug("委外单结算：=========结束(耗时：{$time})==========");
        $bomModel = new BomModel();
        if ($flag == true) {
            $this->logger->debug("出库单：{$bomId}，标记为完成");
            $bomModel->updateBom($bomUuid, ['status' => 1]);
        } else {
            $this->logger->debug("出库单：{$bomId}，标记为欠料");
            $bomModel->updateBom($bomUuid, ['status' => 2]);
        }
    }


}